/*
 * UDPServer.cpp
 *
 *  Created on: Dec 29, 2014
 *      Author: toti
 */

#include <Connectivity/UDPServer.hpp>

UDPServer::UDPServer(std::string &listeningAddress, std::string &port) {

	this->listeningAddress = listeningAddress;
	this->port = port;

	init();
}

void UDPServer::init() {

	/* Resolve the multicast group address */
	hints.ai_family = PF_UNSPEC;
	hints.ai_flags = AI_NUMERICHOST;

	getaddrinfo(listeningAddress.c_str(), NULL, &hints, &multicastAddr);

	/* Get a local address with the same family (IPv4 or IPv6) as our multicast group */
	hints.ai_family = multicastAddr->ai_family;
	hints.ai_socktype = SOCK_DGRAM;
	hints.ai_flags = AI_PASSIVE; /* Return an address we can bind to */
	getaddrinfo(NULL, port.c_str(), &hints, &localAddr);

	/* Create socket for receiving datagrams */
	sock = socket(localAddr->ai_family, localAddr->ai_socktype, 0);

	/* lose the pesky "Address already in use" error message */
	int parameter = 1;
	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &parameter, sizeof(int));

	/* Bind to the multicast port */
	bind(sock, localAddr->ai_addr, localAddr->ai_addrlen);


    struct ipv6_mreq multicastRequest;  /* Multicast address join structure */

    /* Specify the multicast group */
    memcpy(&multicastRequest.ipv6mr_multiaddr,
	     &((struct sockaddr_in6*)(multicastAddr->ai_addr))->sin6_addr,
	     sizeof(multicastRequest.ipv6mr_multiaddr));

    /* Accept multicast from any interface */
    multicastRequest.ipv6mr_interface = 0;

    /* Join the multicast address */
    setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest));


    freeaddrinfo(localAddr);
    freeaddrinfo(multicastAddr);



}

int UDPServer::receiveDatagram(size_t len, void *data) {

	unsigned int addressLen = sizeof(struct sockaddr_in6);

	return recvfrom(sock, data, len, 0, (struct sockaddr *)&sender, &addressLen);

}

int UDPServer::getSock(){

	return sock;

}
